/**
  *执行需要测试的程序
 *cmdstring为程序命令
 *a为测试用例路径
 *1正确结束，VT超时，VM超内存,VR输出错误,RE运行错误</returns>
*/
int protest( const char *cmdstring ,char *a)
{       
        static int i=0;/*记录检测次数*/
        pid_t pid;//记录创建进程的进程号
        int flag=0;//用于运行结束状态
        int status=1;//用于记录分配状态
       
        if((pid=vfork())<0)//创建进程
       {
        	status=-1;//创建失败
       }
        else if(pid==0)//子进程
        { 
          	struct rlimit limit;//用于权限限制的结构体
          	FILE *in,*out;//重定向用于输入输出流
          	
		getrlimit(RLIMIT_CPU,&limit);
          	limit.rlim_cur=TL;
          	setrlimit(RLIMIT_CPU,&limit);
          	/*进程时间限制为TLs*/
            
	      getrlimit(RLIMIT_CORE,&limit);
          	limit.rlim_cur=0;
          	setrlimit(RLIMIT_CORE,&limit);
          	/*禁止制做核心转储*/
            if(strcmp(theout.la,"java")!=0){//java要启动虚拟你不限制其内存不是java限制其内存
		getrlimit(RLIMIT_AS,&limit); 
	        limit.rlim_cur=ML;
            	setrlimit(RLIMIT_AS,&limit);
            	/*限制内存使用MLb*/
		}					
	        getrlimit(RLIMIT_FSIZE,&limit); 
            	limit.rlim_cur=1024*1024;
            	setrlimit(RLIMIT_FSIZE,&limit);
         	/*文件大小限制1MB*/

         	in=freopen(a,"r",stdin);/*重定向输入输出*//*PUB/0101/0*/
         	out=freopen(thein.outtemp,"w",stdout);/*PUBT/kinet0101*/

            if(strcmp(theout.la,"java")!=0)//如果检测的不适java
                execvp(cmdstring,NULL);//执行程序
            else{	
                char temppath[100];
                strcpy(temppath,path);
                strcat(temppath,PUBT);
                execlp("java"," ","-classpath",temppath,cmdstring,NULL);	//执行java程序
                    }

         	fclose(in);//关闭文件流
         	fclose(out);
        } 
                else{
                        if(i==CM-1){//第CM次测试检测内存占用	
                           getM((int)pid);/*如果代码顺利运行CM此获取其内存占用量否则不检测*/
		 		}
                 	wait(&status);   //等待进程结束             
                 	if(WIFEXITED(status))//检测是否为正常结束
			{
                 	  flag=1;/*进程正常停止*/ 
                 	}
                	else if(WIFSIGNALED(status))//检测是否异常结束
			{
	                      int sig = WTERMSIG(status);//获取异常结束原因

	                      if(sig == SIGXCPU)
			   	    {
                        	flag=VT;/*超时*/
                             	     }
                            if(sig == SIGXFSZ)
			    	     {
                 	 	     flag=VR;/*输出越权*/
                	             }
                	     	    if(sig == SIGSEGV)
			   	     {
                	            flag=RE;
                	               /*运行时错误*/
                           	     }
              	          if(sig==SIGKILL)
			   	    {
                			flag=VM;/*超越内存限制*/         
                       	   	    }
                      }
                  
                 }    
    
     i++;//测试次数加一
     return(flag);
}
